package com.impetus.project.skilltest.client.pages;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.impetus.project.skilltest.client.stub.TestService;
import com.impetus.project.skilltest.client.stub.TestServiceAsync;
import com.impetus.project.skilltest.common.Constants;
import com.impetus.project.skilltest.common.SkillTestException;
import com.impetus.project.skilltest.common.dataobject.ProgrammingQuestion;
import com.impetus.project.skilltest.common.dataobject.Question;
import com.impetus.project.skilltest.common.dataobject.TestTransData;

public class TestParticipationPage 
{
	private static final TestServiceAsync testService = GWT.create(TestService.class);
	
	private PageData pageData;
	private String status;
	private Label statusLable;
	
	public  boolean loadPage(final PageData pageData)throws SkillTestException
	{
		try
		{
			statusLable = new Label();
			statusLable.setWordWrap(true);
			this.pageData = pageData;
			
			testService.getNextQuestion(pageData.getUser(), pageData.getTest(),
				new AsyncCallback<Question>() {
					public void onSuccess(Question result) {
						try{
							pageData.setQuestion(result);
							displayQuestion(pageData);
						}catch(Throwable t){
							pageData.setExceptionCaught(t);
							new ErrorPage().loadPage(pageData);
						}
					}
					public void onFailure(Throwable caught) {
						pageData.setExceptionCaught(caught);
						new ErrorPage().loadPage(pageData);
					}
			});
			return true;
		}
		catch(Throwable ex)
		{
			ex.printStackTrace();
			if(ex instanceof SkillTestException){
				throw (SkillTestException)ex;
			}else{
				throw new SkillTestException(ex);
			}
		}
	}
	
	private void displayQuestion(PageData pageData)throws SkillTestException
	{
		if(pageData.getQuestion() == null)
		{
			throw new SkillTestException("Question data not found");
		}
		if(pageData.getQuestion() instanceof ProgrammingQuestion)
		{
			displayProgrammingQuestion((ProgrammingQuestion)pageData.getQuestion());
		}
		else
		{
			throw new SkillTestException("Unsupported question type: ["+pageData.getQuestion().getqType()+"]");
		}
	}
	
	private void displayProgrammingQuestion(ProgrammingQuestion q)
	{
		statusLable.setWordWrap(true);
		statusLable.setText("Implement the following method:");
		
		Label text = new Label();
		text.setWordWrap(true);
		text.setText(q.getqText());
		
		StringBuffer signature = new StringBuffer();
		signature.append("public ")
		.append(q.getReturnType()).append(' ')
		.append(q.getMethodName()).append(' ')
		.append('(');
		if(q.getArg1() != null && q.getArg1() != "")
		{
			signature.append(q.getArg1());
			if(q.getArg2() != null && q.getArg2() != "")
			{
				signature.append(", ").append(q.getArg2());
				if(q.getArg3() != null && q.getArg3() != "")
				{
					signature.append(", ").append(q.getArg3());
					if(q.getArg4() != null && q.getArg4() != "")
					{
						signature.append(", ").append(q.getArg4());
					}
				}
			}		
		}
		signature.append(')')
		.append("\n{\t\n}");
		
		final TextArea ta = new TextArea();
	    ta.setCharacterWidth(80);
	    ta.setVisibleLines(50);
	    ta.setText(signature.toString());
	    
	    HorizontalPanel submitButtonPanel = new HorizontalPanel();
	    Button evalBut = new Button("Evaluate");
		evalBut.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String status = evaluateAndSaveProgrammingQuestion(ta.getText(), false);
				statusLable.setText(status);
			}});
		submitButtonPanel.add(evalBut);
		
		Button submitBut = new Button("Submit");
		submitBut.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String status = evaluateAndSaveProgrammingQuestion(ta.getText(), true);
				statusLable.setText(status);
			}});
		submitButtonPanel.add(submitBut);
		
		HorizontalPanel menuPanel = TopMenu.drawMenu(pageData);
		
	    VerticalPanel vpanel = new VerticalPanel();
		vpanel.addStyleName("center");
		vpanel.add(menuPanel);
		vpanel.add(text);
		vpanel.add(statusLable);
		vpanel.add(ta);
		vpanel.add(submitButtonPanel);
		
		RootPanel.get().clear();
	    RootPanel.get().add(vpanel);
	}
	
	private String evaluateAndSaveProgrammingQuestion(String program, boolean save){
		try{
			TestTransData transData = new TestTransData();
			transData.setCandidateid(pageData.getUser().getCandidateid());
			transData.setqType(Constants.QUESTION_TYPE.PROGRAMMING);
			transData.setSubmitedData(program);
			transData.setTestid(pageData.getTest().getTestid());
			transData.setQuestionId(pageData.getQuestion().getQuestionId());
			
			if(save){
				testService.evaluateAndSaveProgrammingQuestion(transData, new AsyncCallback<TestTransData>() {
					public void onSuccess(TestTransData result) {
						if(Constants.ANSWER_STATUS.ERROR.equals(result.getStatus())){
							status = result.getStatus() + ": " + result.getErrorText();
						}else{
							status = result.getStatus();
						}
					}
					public void onFailure(Throwable caught) {
						status = caught.getMessage();
					}
				});
			}else{
				testService.evaluateProgrammingQuestion(transData, new AsyncCallback<TestTransData>() {
					public void onSuccess(TestTransData result) {
						if(Constants.ANSWER_STATUS.ERROR.equals(result.getStatus())){
							status = result.getStatus() + ": " + result.getErrorText();
						}else{
							status = result.getStatus();
						}
					}
					public void onFailure(Throwable caught) {
						status = caught.getMessage();
					}
				});
			}
		}
		catch(Throwable t){
			status = t.getMessage();
		}
		return status;
	}
}
